package com.hicorp.segment.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hicorp.segment.pojo.types.DataOptionType;
import com.hicorp.segment.service.BasicMasterSubService;
import com.hicorp.segment.utils.BasicSqlOption;
import com.hicorp.segment.utils.ResultBean;
import com.hicorp.segment.utils.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import static com.hicorp.segment.utils.BasicSqlOption.selectAll;

@Service
@Slf4j
public class BasicMasterSubServiceImpl implements BasicMasterSubService {
    /**
     * 查询所有
     *
     * @param masterTableName 主表表名
     * @return 查询到的结果
     */
    @Override
    public Object queryInfo(String masterTableName) {
        return selectAll(masterTableName, log);
    }

    /**
     * 新增
     *
     * @param record          新增数据
     * @param masterTableName 主表表名
     * @param subTableName    子表表名
     * @param masterFiledName 主表键名
     * @param subFiledName    子表键名
     * @return 变更结果
     */
    @Override
    public ResultBean<Void> addRecord(Object record, String masterTableName, String subTableName, String masterFiledName, String subFiledName) {
        try {
            // 大驼峰mapper名，用于反射.
            String upperCamelTableName = BasicSqlOption.setCamel2UpperCamel(masterTableName);

            // pojo的Class
            Class<?> masterTableClass = Class.forName("com.hicorp.segment.pojo.po." + upperCamelTableName);

            // 主表新增，返还主表新增的数据项.
            Object convertValue = BasicSqlOption.changeRecord(record, masterTableName, upperCamelTableName, masterTableClass, "insert");

            // 外键绑定的主表属性名.
            Field masterField = masterTableClass.getDeclaredField(masterFiledName);
            // 开启强制执行
            masterField.setAccessible(true);
            // 获取外键绑定的主表字段的具体值.
            Object masterFiledValue = masterField.get(convertValue);

            // 大驼峰mapper名，用于反射.
            String upperCamelSubTableName = BasicSqlOption.setCamel2UpperCamel(subTableName);

            // 小驼峰mapper名, 用于注入.
            String lowerCamelSubTableName = BasicSqlOption.setCamel2LowerCamel(subTableName);

            // 子表的Class
            Class<?> subTableClass = Class.forName("com.hicorp.segment.pojo.po." + upperCamelSubTableName);

            // 外键子表字段名.
            Field subTableField = subTableClass.getDeclaredField(subFiledName);
            // 开启强制执行
            subTableField.setAccessible(true);

            // 获取children属性
            Field children = masterTableClass.getDeclaredField("children");
            // 开启强制执行
            children.setAccessible(true);

            // 子表原始数据
            List<?> originSubRecord = new ArrayList<>();
            // 获取发送过来的数据中的子表数据.
            if (children.get(convertValue) instanceof List<?>) {
                originSubRecord = (List<?>) children.get(convertValue);
            }

            // 往数据库存的添加了外键的子表数据.
            List<Object> subRecordList = new ArrayList<>();

            // 为子表数据添加外键值.
            ObjectMapper objectMapper = new ObjectMapper();
            for (Object item :
                    originSubRecord) {
                Object convertSubTableValue = objectMapper.convertValue(item, subTableClass);
                subTableField.set(convertSubTableValue, masterFiledValue);
                subRecordList.add(convertSubTableValue);
            }

            // 子表mapper的Class
            Class<?> subMapperClass = Class.forName("com.hicorp.segment.mapper." + upperCamelSubTableName + "Mapper");

            // 子表Mapper名(小驼峰名，用于注入)
            String subMapperName = lowerCamelSubTableName + "Mapper";

            // 利用SpringUtil工具类注入子表Mapper.
            Object subMapper = SpringUtil.getBean(subMapperName);

            // 利用反射获取方法.
            Method subMapperMethod = subMapperClass.getMethod("insertList", List.class);
            // 执行新增方法.
            subMapperMethod.invoke(subMapper, subRecordList);
            return new ResultBean<>(200, "添加成功!");
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return new ResultBean<>(400, "添加失败!");
        }
    }

    /**
     * 主子表编辑
     *
     * @param record          编辑的数据
     * @param masterTableName 主表表名
     * @param subTableName    子表表名
     * @param masterFiledName 主表键名
     * @param subFiledName    子表键名
     * @return 编辑结果(成功与否)
     */
    @Override
    public ResultBean<Void> editRecord(Object record, String masterTableName, String subTableName, String masterFiledName, String subFiledName) {
        try{
            // 大驼峰mapper名，用于反射.
            String upperCamelTableName = BasicSqlOption.setCamel2UpperCamel(masterTableName);

            // pojo的Class
            Class<?> masterTableClass = Class.forName("com.hicorp.segment.pojo.po." + upperCamelTableName);

            // 主表编辑，返还主表编辑的数据项.
            Object convertValue = BasicSqlOption.changeRecord(record, masterTableName, upperCamelTableName, masterTableClass, DataOptionType.UPDATE.getMethodName());

            return new ResultBean<>(200, "修改成功!");
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ResultBean<>(400, "修改失败!");
        }
    }

    /**
     * 批量删除
     *
     * @param masterTableName 主表表名
     * @param ids             被删除的项的id集合
     * @return 删除结果
     */
    @Override
    public Object batchDeleteRecord(String masterTableName, List<Long> ids) {
        return null;
    }

    /**
     * 按照某个字段进行搜索
     *
     * @param masterTableName 主表表名
     * @param fieldName       字段名
     * @param fieldValue      字段内容
     * @return 搜索的结果
     */
    @Override
    public Object selectRecords(String masterTableName, String fieldName, String fieldValue) {
        return null;
    }
}
